/** ***********************************************************************************
* @file         flash_buffer.h
* @brief        FLASH底层驱动接口
* @details      主要用来进行对FLASH底层驱动接口进行读、写、擦除等操作
* @author       杨小珛
* @date         2020/03/03
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#ifndef FLASH_BUFFER_H
#define FLASH_BUFFER_H

#include "os_app.h"

#define     SF_WRITING                  0x01
#define     SF_WRITE_DONE               0x02
#define     SF_CUR_SEND                 0x04
#define     SF_HIS_SEND                 0x08
#define     SF_DELETE                   0x10

#define     SFBUF_HIS_READ_NUM          10  // 历史数据地址缓冲数
#define     SPI_BUF_INVALID_ADDR        0xFFFFFFFF
#define     SPI_DATA_VALID_MASK         0x13
#define     SPI_DATA_VALID_FLAG         0x10

/*-------------------------------------------------------------------------
                       数据类型(data type)
  -----------------------------------------------------------------------*/
typedef enum
{
    SFBUF_DATA_DEFAULT            = 0x00,   // 默认数据
    SFBUF_DATA_CURRENT,                      // 当前数据
    SFBUF_DATA_HISTORY,                      // 历史数据
} sfbuf_type_e;

/*-------------------------------------------------------------------------
                       多包数据状态(multi-pack data status)
  -----------------------------------------------------------------------*/
typedef enum
{
    SFBUF_CYC_DEFAULT            = 0x00,     // 默认数据
    SFBUF_CYC_START,                     		// 循环数据已经产生
} sfbuf_cycle_e;

typedef enum
{
    SFBUF_ST_DEFAULT            = 0x00,     // 默认数据
    SFBUF_ST_MPD_START,                     // 多包数据开始
    SFBUF_ST_MPD_MEDIAL,                    // 多包中间数据
    SFBUF_ST_MPD_END,                       // 多包数据结束
} sfbuf_status_e;

typedef enum
{
    SFB_SEARCH_FRONT,		///< 往地址大方向
    SFB_SEARCH_BACK,		///< 往地址小方向
    SFB_SEARCH_CYCLE,		///< 循环读取
} sfb_direction_e;

#define	CURRENT_PAGE_STATE		0x00000000		/// < 处于当前页状态
#define	TURN_PAGE_STATE		0x00000001		/// < 处于翻页状态

/*-------------------------------------------------------------------------
        Spi Flash 缓冲索引结构(Spi Flash buffer index structure)
  -----------------------------------------------------------------------*/
typedef struct
{
	// 写位操作时经常出现问题( NOR FLASH 没有问题 )
	union
    {
        uint8_t     ucsdindex;       // SPI Flash索引状态
        struct
        {
            uint8_t bwrite      : 1;  // 数据开始写入 0 开始写入 
            uint8_t bread       : 1;  // 数据开始读取 0 开始读取
            uint8_t bwrdone     : 1;  // 数据写入完成 0 写入完成 
            uint8_t bredone     : 1;  // 数据读取完成 0 读取完成
            uint8_t bdel        : 1;  // 数据删除 0 数据删除
            uint8_t bsenddone   : 1;  // 数据发送完成  0 发送完成
            uint8_t brsv        : 2;  // 保留
        };
    };
    uint8_t     ucsfcrc; 	// 数据校验
    uint16_t    usdatalen; // 数据长度
} sfb_index_t;

/*-------------------------------------------------------------------------
        Spi Flash 缓冲信息(Spi Flash buffer information)
--------------------------------------------------------------------------*/
typedef struct 
{
    volatile    uint32_t    handle_add; // SFB handle 数据存储区
    volatile    uint32_t    base_add;   // 信息存储单位基础地址
    volatile    uint32_t    sec_sz;     // 存储器块尺寸 
    volatile    uint32_t    sectors;    // 信息存储空间块数量
    volatile    uint32_t    unit_sz;    // 存储信息长度 
    volatile    uint32_t    sec_units;  // 存储器每块存储的信息条数
}sfb_setting_t;

typedef struct
{
    volatile    uint32_t    curwraddr;      // 当前写入数据地址
    volatile    uint32_t    currdaddr;      // 当前数据读出地址
}sfb_addr_record_t;

typedef struct
{
    volatile    uint32_t    write;          // 当前有效的数目
    volatile    uint32_t    read;      		// 以完成数目
}sfb_buf_statistics_t;

/*-------------------------------------------------------------------------
        Spi Flash 存储信息结构体
--------------------------------------------------------------------------*/
typedef struct 
{   
    volatile uint32_t sfb_st;           /* SFB当前的状态 */
    sfb_setting_t sfb_set;              /* SFB设置的地址 */
    sfb_addr_record_t sfb_addr;         /* SFB记录的地址 */
    sfb_buf_statistics_t sfb_buf_cache; /* SFB记录的数量 */
}sfb_buf_rt_t;

/*-------------------------------------------------------------------------
        Spi Flash 存储的HANDLE 信息
--------------------------------------------------------------------------*/
typedef struct 
{   
    sfb_addr_record_t addr;             /* SFB记录的地址 */
    sfb_buf_statistics_t cache;         /* SFB记录的数量 */
    volatile uint32_t crc32;            /* 数据校验*/
}sfb_buf_handle_t;

#define   SFB_SPACE_STATE_OK    ( 0x00000000 )     
#define   SFB_SPACE_STATE_ERR   ( 0x00000001 )     

#define   SPIBUF_SECTOR_OFFSET_GET(addr, min_sec)		(addr & (min_sec - 1))
#define   SPIBUF_SECTOR_BASE_ADDR_GET(addr, min_sec)		(addr & ~(min_sec - 1))
#define   SPIBUF_BLOCK_OFFSET_GET(addr, min_blk)			(addr & (min_blk - 1))
#define   SPIBUF_SECTOR_LAST_UNIT_ADDR_GET(buf, addr)	(SPIBUF_SECTOR_BASE_ADDR_GET(addr, buf->sfb_set.sec_sz) + ((buf->sfb_set.sec_units - 1) * buf->sfb_set.unit_sz))
#define   SPIBUF_END_ADDR_GET(buf)						(buf->sfb_set.base_add + buf->sfb_set.sectors * buf->sfb_set.sec_sz)

/****************************************************************************************
* 系统参数存储消息格式
******************************************************************************************/
typedef struct
{
	volatile uint32_t infor_len;
	volatile uint8_t *infor_p;
	volatile uint32_t infor_crc;
}sfb_buf_store_infor_s;

/** ****************************************************************************
* @remarks       uint32_t sfb_bbt_tables_init(void)
* @brief         外部FLASH bbt数据列表初始化
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern uint32_t sfb_bbt_tables_init(void);

/** ****************************************************************************
* @remarks       uint32_t sfb_handle_init( sfb_buf_rt_t *sfb_handle ,const sfb_setting_t *sfb_set )
* @brief         SFB 数据存储空间，句柄数据初始化
* @param[in]     *sfb_handle SFB句柄数据地址
* @param[in]     *sfb_set SFB设置的参数
* @param[out]    无
* @return        返回 存储的数据的句柄当前位置
* @attention     无
*******************************************************************************/
extern uint32_t sfb_handle_init( sfb_buf_rt_t *sfb_handle ,const sfb_setting_t *sfb_set );

/** ****************************************************************************
* @remarks       uint32_t  sfb_block_reset( uint32_t addr, uint32_t sectors )
* @brief         SFB 数据空间复位操作
* @param[in]     addr 开始地址
* @param[in]     sectors 选择的块数量
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void  sfb_block_reset( uint32_t addr, uint32_t sectors );

/** ****************************************************************************
* @remarks       void sfb_address_check( sfb_buf_rt_t *sfb_handle )
* @brief         检测SFB 地址的合法性
* @param[in]     *sfb_handle 读写数据的句柄
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void sfb_address_check( sfb_buf_rt_t *sfb_handle );

/** ****************************************************************************
* @remarks       uint32_t sfb_unit_write( sfb_buf_rt_t *sfb_handle , uint8_t* data , sfb_index_t *index)
* @brief         数据写入到外部FLASH 中
* @param[in]     *sfb_handle 读写数据的句柄
* @param[in]     *data 写入的数据地址
* @param[in]     *index 写入数据的状态
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern uint32_t sfb_unit_write( sfb_buf_rt_t *sfb_handle , uint8_t *data , sfb_index_t *index);

/** ****************************************************************************
* @remarks       uint32_t sfb_unit_read( sfb_buf_rt_t *sfb_handle , sfb_direction_e direct, uint32_t unit, uint32_t size, uint8_t* data ,sfb_index_t* rindex)
* @brief         读取FLASH 数据
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[in]     direct 读取数据的方向 (SFB_SEARCH_CYCLE 默认为循环读取) 
* @param[in]     unit 读取的最小单元数 (默认为1 )
* @param[in]     size 读取的最长数据
* @param[in]     sf_index_s* rindex 读取数据的状态
* @param[out]    无
* @return        pdPASS 读取数据成功 ，pdFAIL 读取数据失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_unit_read( sfb_buf_rt_t *sfb_handle , sfb_direction_e direct, uint32_t unit, uint32_t size, uint8_t* data ,sfb_index_t* rindex);

/** ****************************************************************************
* @remarks       uint32_t sfb_directly_read( sfb_buf_rt_t *sfb_handle , sfb_direction_e direct ,uint32_t unit, uint32_t size,uint8_t* data ,sfb_index_t *rindex)
* @brief         读取FLASH 数据
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[in]     direct 读取数据的方向 (SFB_SEARCH_CYCLE 默认为循环读取) 
* @param[in]     unit 读取的最小单元数 (默认为1 )
* @param[in]     size 读取的最长数据
* @param[in]     sf_index_s* rindex 读取数据的状态
* @param[out]    无
* @return        pdPASS 读取数据成功 ，pdFAIL 读取数据失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_directly_read( sfb_buf_rt_t *sfb_handle , sfb_direction_e direct ,uint32_t unit, uint32_t size,uint8_t* data ,sfb_index_t *rindex);

/** ****************************************************************************
* @remarks       void sfb_read_reset( sfb_buf_rt_t *sfb_handle)
* @brief         复位方向读数据地址，将读取数据的地址和条数设置为和写数据相同
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void sfb_read_reset( sfb_buf_rt_t *sfb_handle);

/** ****************************************************************************
* @remarks       uint32_t sfb_send_succ( sfb_buf_rt_t *sfb_handle )
* @brief         数据发送成功 写发送成功标识
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    无
* @return        pdPASS 标志写成功 ，pdFAIL 标志写失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_send_succ( sfb_buf_rt_t *sfb_handle );

/** ****************************************************************************
* @remarks       uint32_t sfb_delete_all( sfb_buf_rt_t *sfb_handle )
* @brief         删除所有数据
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    无
* @return        pdPASS 标志写成功 ，pdFAIL 标志写失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_delete_all( sfb_buf_rt_t *sfb_handle );

/** ****************************************************************************
* @remarks       uint32_t sfb_read_index( uint32_t addr, sfb_index_t* xindex)
* @brief         读取存储单元内的存储信息
* @param[in]     addr 读取数据的地址
* @param[out]    *xindex 返回的数据条目的地址数据
* @return        pdPASS 标志写成功 ，pdFAIL 标志写失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_read_index( uint32_t addr, sfb_index_t *xindex);

/** ****************************************************************************
* @remarks       uint32_t sfb_units_cn_get( sfb_buf_rt_t *sfb_handle, uint32_t *unit_num )
* @brief         获取数据的单元数据
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    *unit_num 返回的数据条目的地址数据
* @return        pdPASS 成功 ，pdFAIL 失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_units_cn_get( sfb_buf_rt_t *sfb_handle, uint32_t *unit_num );

/** ****************************************************************************
* @remarks       uint32_t sfb_write_position_get( sfb_buf_rt_t *sfb_handle, uint32_t *position )
* @brief         获取当前写的位置
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    *position 当前写的位置
* @return        pdPASS 成功 ，pdFAIL 失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_write_position_get( sfb_buf_rt_t *sfb_handle, uint32_t *position );

/** ****************************************************************************
* @remarks       uint32_t sfb_read_position_get( sfb_buf_rt_t *sfb_handle, uint32_t *position )
* @brief         获取当前读的位置
* @param[in]     * sfb_handle 读取flash 数据的句柄
* @param[out]    *position 当前读的位置
* @return        pdPASS 成功 ，pdFAIL 失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_read_position_get( sfb_buf_rt_t *sfb_handle, uint32_t *position );

/** ****************************************************************************
* @remarks       uint32_t sfb_read_buf(uint32_t addr, uint8_t* buf, uint16_t len)
* @brief         读取FLASH 数据
* @param[in]     addr flash地址
* @param[in]     size 读取数据的长度
* @param[out]    *pbuff 读取数据地址
* @return        无
* @attention     无
*******************************************************************************/
extern uint32_t sfb_read_buf(uint32_t addr, uint8_t* buf, uint16_t len);

/** ****************************************************************************
* @remarks       uint32_t sfb_write_buf(uint32_t addr, uint8_t* buf, uint16_t len)
* @brief         写FLASH 空间数据 
* @param[in]     addr 写空间地址
* @param[in]     *pbuff 写数据地址
* @param[in]     size 写数据长度
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern uint32_t sfb_write_buf(uint32_t addr, uint8_t* buf, uint16_t len);

/** ****************************************************************************
* @remarks       uint32_t sfb_write_handle_position( sfb_buf_rt_t *sfb_handle, uint32_t *position )
* @brief         写SFB HANDLE 当前的位置 
* @param[in]     addr 写空间地址
* @param[out]    *position 当前的位置
* @return        pdPASS 成功 ，pdFAIL失败
* @attention     无
*******************************************************************************/
extern uint32_t sfb_write_handle_position( sfb_buf_rt_t *sfb_handle, uint32_t *position );

/** ****************************************************************************
* @remarks       uint32_t sfb_write_par_store( uint32_t addr , sfb_buf_store_infor_s *infor )
* @brief         系统参数写入FLASH 内存接口 带CRC32校验
* @param[in]     addr 写入参数地址 
* @param[in]     *infor 写入参数信息
* @param[out]    无
* @return        >0 写入的数据长度  =0 写入的数据过长 或者指针为空
* @attention     无
*******************************************************************************/
extern uint32_t sfb_write_par_store( uint32_t addr , sfb_buf_store_infor_s *infor );

/** ****************************************************************************
* @remarks       uint32_t sfb_read_par_store( uint32_t addr , sfb_buf_store_infor_s *infor )
* @brief         系统参数读取FLASH 内存接口 带CRC32校验
* @param[in]     addr 读取参数地址 
* @param[out]    *infor 读取参数信息
* @return        >0 返回读取数据的长度   =0 数据CRC错误 或者读取的数据大于1024 或者 等于0
* @attention     无
*******************************************************************************/
extern uint32_t sfb_read_par_store( uint32_t addr , sfb_buf_store_infor_s *infor );

#endif

